package com.info.zhiduoduo.pay.sdk.zhaoshangbank.util;

import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import lombok.extern.slf4j.Slf4j;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.HashMap;

/**
 * 国密免前置/SaaS对接示例，本示例仅供参考，不保证各种异常场景运行，请勿直接使用，如有错漏请联系对接人员。运行时，请使用所获取的测试资源替换 用户编号、公私钥、对称密钥、服务商编号等信息。
 */
@Slf4j
public class ZsPayUtil {

    private static Base64.Encoder encoder = Base64.getEncoder();
    private static Base64.Decoder decoder = Base64.getDecoder();

    private static final String ALG_SM = "SM"; // 采用国密算法

    /**
     * @param jObject
     * @param UID
     * @param URL
     * @param bankpubkey
     * @param privkey
     * @param sm4key
     * @return
     * @throws Exception
     */
    public static String doProcess(JsonObject jObject, String UID, String URL, String function, String bankpubkey, String privkey, String sm4key) throws Exception {
        JsonObject object = new JsonObject();
        // 签名
        object.addProperty("sigdat", "__signature_sigdat__");
        object.addProperty("sigtim", DCHelper.getTime());
        jObject.add("signature", object);
        String source = DCHelper.serialJsonOrdered(jObject);
//        System.out.println("签名原文: " + source);
        byte[] signature1 = DCCryptor.CMBSM2SignWithSM3(getID_IV(UID), decoder.decode(privkey), source.getBytes(StandardCharsets.UTF_8));
        String sigdat1 = new String(encoder.encode(signature1));
//        System.out.println("签名结果: " + sigdat1);
        object.addProperty("sigdat", sigdat1);

        // SM4-CBC加密
        String plaintxt = jObject.toString();
        log.info("加密前req:  " + plaintxt);
        byte[] enInput = DCCryptor.CMBSM4EncryptWithCBC(sm4key.getBytes(), getID_IV(UID), plaintxt.getBytes(StandardCharsets.UTF_8));

        String req = new String(encoder.encode(enInput));
        System.out.println("加密后req:  " + req);

        // 发送请求
        HashMap<String, String> map = new HashMap<>();
        map.put("UID", UID);
        map.put("ALG", ALG_SM);
        map.put("DATA", URLEncoder.encode(req, "utf-8"));
        map.put("FUNCODE", function);
        String res = DCHelper.doPostForm(URL, map);
        log.info("招商接口访问返回res:{}" , res);
        try {
            decoder.decode(res);
        } catch (Exception e) {
            log.error("招商接口访问返回错误res:{}.msg:{}", res, e);
            return null;
        }

        // 解密请求
        String resplain = new String(DCCryptor.CMBSM4DecryptWithCBC(sm4key.getBytes(), getID_IV(UID), decoder.decode(res)), StandardCharsets.UTF_8);
        log.info("招行返回数据res decrypt: {}", resplain);

        // 验签
        JsonObject object2 = new GsonBuilder().create().fromJson(resplain, JsonObject.class);
        JsonObject object3 = object2.getAsJsonObject("signature");
        String resSign = object3.get("sigdat").getAsString();
        object3.addProperty("sigdat", "__signature_sigdat__");
        object2.add("signature", object3);
        String resSignSource = DCHelper.serialJsonOrdered(object2);

        boolean verify = DCCryptor.CMBSM2VerifyWithSM3(getID_IV(UID), decoder.decode(bankpubkey), resSignSource.getBytes(StandardCharsets.UTF_8), decoder.decode(resSign));
        if (!verify) {
            log.error("招行验签失败！验签原文：{}", resSignSource);
        }
        return resSignSource;
    }

    private static byte[] getID_IV(String UID) {
        String uid = UID; // 请替换为实际的用户UID
        String userid = uid + "0000000000000000";
        return userid.substring(0, 16).getBytes();
    }

}
